/**
 * Copyright (C), 2001-2031, www.bosssof.com.cn
 * FileName: ResourceServiceImpl.java
 * Author: YuXingZh
 * Date: 5/6/2024 上午8:45
 * Description:
 * 资源管理实现类
 * History:
 * Date          Author   Version  Desc
 * 2024-01-01    bosssoft  1.0.0   initialize this file
 */
package com.bosssoft.g1.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bosssoft.g1.common.annotation.CommonFieldStuffer;
import com.bosssoft.g1.common.annotation.MethodTypeEnum;
import com.bosssoft.g1.common.exception.parse.BusinessException;
import com.bosssoft.g1.dto.PageDTO;
import com.bosssoft.g1.dto.ResourceDTO;
import com.bosssoft.g1.dto.RoleDTO;
import com.bosssoft.g1.dto.UserDTO;
import com.bosssoft.g1.entity.Node;
import com.bosssoft.g1.entity.Resource;
import com.bosssoft.g1.entity.RoleResource;
import com.bosssoft.g1.mapper.ResourceMapper;
import com.bosssoft.g1.mapper.RoleResourceMapper;
import com.bosssoft.g1.mapper.UserMapper;
import com.bosssoft.g1.service.ResourceService;
import com.bosssoft.g1.utils.IdGenerator;
import com.bosssoft.g1.vo.IdNameVO;
import com.bosssoft.g1.vo.ResourceVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;

import javax.validation.constraints.NotEmpty;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: ResourceServiceImpl
 * @description: 解决什么问题：
 * 演示线程池的正确使用
 * 主要方法和数据成员：
 * methodxx 使用 ThreadPoolExecutor创建线程进行任务操作
 * 注意事项：
 * 例如：该类需要从容器获取不可以new
 * @author: YuXingZh
 * @date: 5/6/2024上午8:45
 * @since 1.0
 **/
@Slf4j
@Service
@Validated
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * 角色资源mapper 对应basic_role_resource表
     */
    @Autowired
    private RoleResourceMapper roleResourceMapper;
    @Autowired
    private IdGenerator idGenerator;

    /**
     * @param name
     * @return
     */
    @Override
    public PageInfo<ResourceVO> queryByName(String name, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        // 根据名称查询资源
        Example example = new Example(Resource.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("name", "%" + name + "%");
        List<Resource> resources = resourceMapper.selectByExample(example);
        List<ResourceVO> resourceVOList = new ArrayList<>();
        for (Resource resource : resources) {
            ResourceVO resourceVO = new ResourceVO();
            BeanUtil.copyProperties(resource, resourceVO);
            resourceVOList.add(resourceVO);
        }
        return new PageInfo<>(resourceVOList);
    }

    /**
     * @param id
     * @return
     */
    @Override
    public PageInfo<ResourceVO> queryById(Long id, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        // 查询根节点及其子节点
        List<Resource> rootResources = resourceMapper.selectByParentId(id);

        // 构建树形结构
        List<ResourceVO> resourceVOList = buildTree(rootResources);

        // 获取分页信息
        PageInfo<ResourceVO> pageInfo = new PageInfo<>(resourceVOList);
        return pageInfo;
    }

    /**
     * 增加资源
     *
     * @param resourceDTO 资源DTO
     * @return true 成功 false失败
     */
    @Override
    public boolean addResource(ResourceDTO resourceDTO) {
       /* //检查用户的编号是否已经存在
        if(userMapper.userExistByUserCode(userDTO.getCode())){
            log.warn("Role with code {} already exists.", userDTO.getCode());
            throw new BusinessException(String.valueOf(-2L),"该用户编号已存在");
        }*/

        Resource resource = new Resource();
        BeanUtils.copyProperties(resourceDTO, resource);
        // TODO 补充上登录后的信息
        resource.setId(idGenerator.snowflakeId());
        resource.setStatus((byte) 1);
        resource.setCreatedBy(1L);
        resource.setCreatedTime(DateUtil.date());
        resource.setUpdatedTime(DateUtil.date());
        resource.setVersion(1L);
        resource.setOrgId(1L);
        resource.setAction((byte) 0);
        resource.setRemark("");

        int insert = resourceMapper.insert(resource);
        if (insert == 1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 通过 id 查询资源
     *
     * @param id 当前行id
     * @return 资源数据
     */
    @Override
    public ResourceVO findById(Long id) {
        Resource resource = resourceMapper.selectByPrimaryKey(id);
        ResourceVO resourceVO = new ResourceVO();
        if (!ObjectUtil.isNull(resource)) {
            BeanUtil.copyProperties(resource, resourceVO);
        }

        return resourceVO;
    }

    /**
     * 资源修改结果保存
     *
     * @param resourceDTO 资源信息包含 id
     * @return true成功 false失败
     */
    @Override
    public int updateResource(ResourceDTO resourceDTO) {
        Resource resource = new Resource();
        BeanUtil.copyProperties(resourceDTO, resource);
        return resourceMapper.updateByPrimaryKey(resource);
    }

    /**
     * 删除单个资源
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Boolean deleteResource(Long id) {
        Resource resource = resourceMapper.selectByPrimaryKey(id);
        if (resource != null ) {
            // 删除角色资源表相关信息
            Example exampleRoleResource = new Example(RoleResource.class);
            exampleRoleResource.createCriteria().andEqualTo("roleId", id);
            roleResourceMapper.deleteByExample(exampleRoleResource);

            int result = resourceMapper.deleteByPrimaryKey(id);
            if (result == 0) {
                // 删除失败
                return false;
            }
            return true;
        } else {
            // 记录不存在
            return false;
        }
    }

    /**
     * 批量删除
     * @param resourceDTOS
     * @return
     */
    @Transactional
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    @Override
    public Boolean batchDeleteResource(@NotEmpty List<ResourceDTO> resourceDTOS){
        try {
            for (ResourceDTO dto : resourceDTOS) {
                Long id = dto.getId();

                if (id == null || id <= 0) {
                    throw new BusinessException("Invalid role ID: " + id);
                }

                // 构建 Example 查询条件
                Example example = new Example(Resource.class);
                example.createCriteria().andEqualTo("id", id);

                // 查询 Role 实体
                List<Resource> roles = resourceMapper.selectByExample(example);
                if (roles.isEmpty()) {
                    throw new BusinessException(String.valueOf(id), "Role not found with the id");
                }

                // 删除角色资源表相关信息
                Example exampleRoleResource = new Example(RoleResource.class);
                exampleRoleResource.createCriteria().andEqualTo("id", id);
                roleResourceMapper.deleteByExample(exampleRoleResource);

                // 删除资源表相关信息
                Example exampleRole = new Example(Resource.class);
                exampleRole.createCriteria().andEqualTo("id", id);
                resourceMapper.deleteByExample(exampleRole);
            }
        } catch (RuntimeException e) {
            // 记录错误日志
            log.error("Error during batch delete role", e);
            // 事务自动回滚
            throw e;
        }
        return true;
    }

    @Override
    public PageInfo<ResourceDTO> getAllRes(PageDTO pageDTO) {
        PageMethod.startPage(pageDTO.getPageNum(),pageDTO.getPageSize());
        //long total = PageHelper.count(()->userMapper.queryUsers(user));
        List<ResourceDTO> resList=resourceMapper.getAllRes();
        return new PageInfo<>(resList);
    }

    @Override
    public List<IdNameVO> getAllSubSystem() {
        List<IdNameVO> idNameVOS = resourceMapper.getAllSubsystem();
        idNameVOS.forEach(idNameVO ->
                System.out.println("原始子系统信息：" + idNameVO.getId() + "," + idNameVO.getName()));
        return idNameVOS;
    }

    /**
     * 根据租户id查询资源树
     * @param id
     * @return
     */
    @Transactional
    @Override
    public List<Node> queryResourceByTenantId(Long id) {
        // 查询数据库并返回租户的所有资源
        System.out.println("传回来的id" + id);
        List<Resource> resources = resourceMapper.queryResourcesByTenantId(id);

        // 打印原始资源列表以调试
        resources.forEach(resource ->
                System.out.println("原始资源: " + resource.getId() + ", " + resource.getName() + ", " + resource.getResourceType())
        );

        // 过滤掉 resourceType 为 1 的资源，确保类型转换正确
        List<Resource> filteredResources = resources.stream()
                .filter(resource -> {
                    System.out.println("过滤检查: " + resource.getId() + ", " + resource.getName() + ", " + resource.getResourceType());
                    return resource.getResourceType() != (byte) 1;
                })
                .collect(Collectors.toList());

        // 打印过滤后的资源列表以调试
        filteredResources.forEach(resource ->
                System.out.println("过滤后的资源: " + resource.getId() + ", " + resource.getName() + ", " + resource.getResourceType())
        );

        // 构建一个 Map，以 id 为键，Node 为值
        Map<Long, Node> nodeMap = new HashMap<>();

        // 首先创建所有的节点并放入 map 中
        for (Resource resource : filteredResources) {
            nodeMap.put(resource.getId(), new Node(resource.getId(), resource.getName()));
        }

        // 创建一个列表来存放根节点
        List<Node> rootNodes = new ArrayList<>();

        // 遍历所有的资源，将每个资源添加到其父节点的 children 列表中
        for (Resource resource : filteredResources) {
            Node node = nodeMap.get(resource.getId());
            if (resource.getParentId() == 1 || resource.getParentId() == -1) {
                // 如果 parentId 是 1 或 -1，则认为是根节点
                rootNodes.add(node);
            } else {
                // 否则，将其添加到其父节点的 children 列表中
                Node parentNode = nodeMap.get(resource.getParentId());
                if (parentNode != null) {
                    parentNode.addChild(node);
                }
            }
        }

        return rootNodes;
    }

    /**
     * 显示增加资源的父亲节点
     * @param id
     * @return
     */
    @Transactional
    @Override
    public List<Node> queryResourceBySusId(Long id){
        // 查询数据库并返回子系统的所有资源
        List<Resource> resources = resourceMapper.queryResourceBySusId(id);

        // 构建一个 Map，以 id 为键，Node 为值
        Map<Long, Node> nodeMap = new HashMap<>();

        // 首先创建所有的节点并放入 map 中
        for (Resource resource : resources) {
            nodeMap.put(resource.getId(), new Node(resource.getId(), resource.getName()));
        }

        // 创建一个列表来存放根节点
        List<Node> rootNodes = new ArrayList<>();

        // 遍历所有的资源，将每个资源添加到其父节点的 children 列表中
        for (Resource resource : resources) {
            Node node = nodeMap.get(resource.getId());
            if (resource.getParentId() == 1 || resource.getParentId() == -1) {
                // 如果 parentId 是 1 或 -1，则认为是根节点
                rootNodes.add(node);
            } else {
                // 否则，将其添加到其父节点的 children 列表中
                Node parentNode = nodeMap.get(resource.getParentId());
                if (parentNode != null) {
                    parentNode.addChild(node);
                }
            }
        }

        return rootNodes;
    }


    private List<ResourceVO> buildTree(List<Resource> resources) {
        List<ResourceVO> resourceVOList = new ArrayList<>();
        for (Resource resource : resources) {
            ResourceVO resourceVO = new ResourceVO();
            BeanUtils.copyProperties(resource, resourceVO);
            resourceVO.setResourceVOs(getChildren(resource.getId()));
            resourceVOList.add(resourceVO);
        }
        return resourceVOList;
    }

    private List<ResourceVO> getChildren(Long parentId) {
        List<Resource> childResources = resourceMapper.selectByParentId(parentId);
        List<ResourceVO> childVOList = new ArrayList<>();
        for (Resource child : childResources) {
            ResourceVO childVO = new ResourceVO();
            BeanUtils.copyProperties(child, childVO);
            childVO.setResourceVOs(getChildren(child.getId()));
            childVOList.add(childVO);
        }
        return childVOList;
    }
}
